package net.guerlab.smart.wx.web.controller;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.guerlab.smart.platform.basic.auth.annotation.IgnoreLogin;
import net.guerlab.smart.platform.basic.auth.enums.TokenType;
import net.guerlab.smart.platform.basic.auth.utils.AbstractJwtHelper;
import net.guerlab.smart.platform.commons.exception.RefreshTokenInvalidException;
import net.guerlab.smart.platform.server.utils.IpUtils;
import net.guerlab.smart.wx.auth.WxUserContextHandler;
import net.guerlab.smart.wx.auth.utils.WxUserJwtHelper;
import net.guerlab.smart.wx.core.domain.LoginResponse;
import net.guerlab.smart.wx.core.domain.WxUserDTO;
import net.guerlab.smart.wx.core.entity.IJwtInfo;
import net.guerlab.smart.wx.core.exception.WxUserInvalidException;
import net.guerlab.smart.wx.service.entity.WxUser;
import net.guerlab.smart.wx.service.service.LoginService;
import net.guerlab.smart.wx.service.service.WxUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 微信相关-控制面板
 *
 * @author guer
 */
public abstract class AbstractWxControlPanelController<LS extends LoginService> {

    protected static final String PREFIX =
            WxUserJwtHelper.PREFIX + AbstractJwtHelper.CONNECTORS + TokenType.SIMPLE_NAME_REFRESH_TOKEN
                    + AbstractJwtHelper.CONNECTORS;

    protected WxUserJwtHelper jwtHelper;

    protected WxUserService wxUserService;

    protected LS loginService;

    @IgnoreLogin
    @ApiOperation("登录")
    @GetMapping("/{appId}/login/{code}")
    public LoginResponse login(@ApiParam(value = "应用ID", required = true) @PathVariable String appId,
            @ApiParam(value = "code", required = true) @PathVariable String code, HttpServletRequest request) {
        return loginService.login(appId, code, IpUtils.getIp(request), request.getHeader("Referer"));
    }

    @IgnoreLogin
    @ApiOperation("刷新Token")
    @GetMapping("/{appId}/refreshToken")
    public LoginResponse refreshToken(@ApiParam(value = "应用ID", required = true) @PathVariable String appId,
            @ApiParam(value = "refreshToken", required = true) @RequestHeader("refreshToken") String refreshToken) {
        if (!refreshToken.startsWith(PREFIX)) {
            throw new RefreshTokenInvalidException();
        }

        String jwtToken = refreshToken.substring(PREFIX.length());
        IJwtInfo info = jwtHelper.parseByRefreshTokenKey(jwtToken);

        if (!Objects.equals(appId, info.getAppId())) {
            throw new RefreshTokenInvalidException();
        }

        return loginService.buildLoginResponse(wxUserService.findUser(info.getAppId(), info.getOpenId()));
    }

    @ApiOperation("获取个人信息")
    @GetMapping
    public WxUserDTO getInfo() {
        return findCurrentWxUser().toDTO();
    }

    protected WxUser findCurrentWxUser() {
        WxUser wxUser = wxUserService.findUser(WxUserContextHandler.getAppId(), WxUserContextHandler.getOpenId());

        if (wxUser == null) {
            throw new WxUserInvalidException();
        }

        return wxUser;
    }

    @Autowired
    public void setJwtHelper(WxUserJwtHelper jwtHelper) {
        this.jwtHelper = jwtHelper;
    }

    @Autowired
    public void setWxUserService(WxUserService wxUserService) {
        this.wxUserService = wxUserService;
    }

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    public void setLoginService(LS loginService) {
        this.loginService = loginService;
    }
}
